package com.wanfajie.smsdistribute.main.fragment.record

import android.app.Service
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.support.v7.view.ActionMode
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.SearchView
import android.text.style.ForegroundColorSpan
import android.view.*
import android.widget.TextView
import com.j256.ormlite.dao.Dao
import com.wanfajie.smsdistribute.MyApplication
import com.wanfajie.smsdistribute.R
import com.wanfajie.smsdistribute.common.activity.BaseActivity
import com.wanfajie.smsdistribute.common.adapter.CheckedRecyclerAdapter
import com.wanfajie.smsdistribute.common.adapter.RecyclerViewHolder
import com.wanfajie.smsdistribute.common.fragment.BaseFragment
import com.wanfajie.smsdistribute.db.bean.sms.SmsBean
import com.wanfajie.smsdistribute.db.helper.SmsDatabaseHelper
import com.wanfajie.smsdistribute.db.repository.SmsRecordRepository
import com.wanfajie.smsdistribute.db.repository.impl.SmsRecordRepositoryImpl
import com.wanfajie.smsdistribute.receiver.sms.SmsSentStatusReceiver
import com.wanfajie.smsdistribute.util.highLight
import com.wanfajie.smsdistribute.util.toast
import java.text.SimpleDateFormat
import java.util.*


class SendRecordFragment : BaseFragment() {

    companion object {
        private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA)
        private val smsRecordRepository: SmsRecordRepository = SmsRecordRepositoryImpl
    }

    private val mCardDrawables: Array<Drawable> by lazy {
        arrayOf(
            resources.getDrawable(R.drawable.ic_card1_gray_16dp),
            resources.getDrawable(R.drawable.ic_card2_gray_16dp)).also {
            it.forEach { dw ->
                dw.setBounds(0, 0, dw.minimumWidth, dw.minimumHeight)
            }
        }
    }

    private val mColorGray by lazy { resources.getColor(R.color.textGray) }
    private val mColorDanger by lazy { resources.getColor(android.R.color.holo_red_dark) }
    private val mHighLightFactory: () -> ForegroundColorSpan by lazy {
        val color = resources.getColor(android.R.color.holo_red_light)
        val factory = { ForegroundColorSpan(color) }
        factory
    }
    private var mFilterId = R.id.filter_all
    private var mSearchKeyword: String = ""
    private var mSearchView: SearchView? = null
    private var mLastClick: SmsBean? = null
    private val mContext: Context get() {
        return context ?: mActivity ?: MyApplication.context
    }

    private val mClipManager: ClipboardManager by lazy {
        mContext.getSystemService(Service.CLIPBOARD_SERVICE) as ClipboardManager
    }
    private var mActivity: BaseActivity? = null
    private lateinit var recordDao: Dao<SmsBean, Int>
    private val mAdapter: CheckedRecyclerAdapter<SmsBean> by lazy {
        object : CheckedRecyclerAdapter<SmsBean>(mActivity!!, emptyList(),
                R.layout.list_item_sent_sms, R.id.checkbox) {
            init {
                setItemCheckable(false)
                setOnLongClickListener {
                    if (isItemCheckable()) {
                        mActionMode?.finish()
                        true
                    } else {
                        mActionMode = mActivity?.startSupportActionMode(mActionCallback)
                        false
                    }
                }
                setOnClickListener {
                    if (!isItemCheckable()) {
                        val vh = it.tag as RecyclerViewHolder
                        mLastClick = vh.tag as SmsBean
                        it.showContextMenu()
                    } else {
                        mActionCallback.updateResendItemVisible()
                    }
                }
            }
            override fun processViewHolder(p0: CheckedViewHolder, p1: SmsBean) {
                p0.get<TextView>(R.id.number).text = highLight(p1.sendTo, mSearchKeyword, mHighLightFactory)
                p0.get<TextView>(R.id.message).text = highLight(p1.message, mSearchKeyword, mHighLightFactory)
                val date = Date(p1.timestamp)
                p0.get<TextView>(R.id.datetime).text = DATE_FORMAT.format(date)
                val status = p0.get<TextView>(R.id.sms_status)
                val statusRes: Int = if (!p1.isComplete) {
                    status.setTextColor(mColorGray)
                    R.string.sending
                } else if (p1.isSuccess) {
                    status.setTextColor(mColorGray)
                    R.string.success
                } else {
                    status.setTextColor(mColorDanger)
                    R.string.failure
                }
                status.setText(statusRes)
                val icon = mCardDrawables.getOrNull(p1.subIndex)
                status.setCompoundDrawables(icon, null, null, null)

                val delBtn = p0.get<TextView>(R.id.btn_delete)
                delBtn.tag = p1
                delBtn.layoutParams.width
                delBtn.setOnClickListener {
                    val bean = it.tag as SmsBean
                    smsRecordRepository.remove(bean)
                    remove(bean)
                }
            }
        }
    }

    private var mActionMode: ActionMode? = null
    private val mActionCallback by lazy {
        object : ActionMode.Callback {
            private var mResendSelected: MenuItem? = null
            fun updateResendItemVisible() {
                mResendSelected?.isVisible = mAdapter.getCheckedCount() > 0 &&
                        mAdapter.getCheckedItemList().all { it.isComplete && !it.isSuccess }
            }

            override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
                return when (item?.itemId) {
                    R.id.delete -> {
                        val checked = mAdapter.getCheckedItemList()
                        recordDao.delete(checked)
                        mAdapter.removeAll(checked)
                        toast(strId = R.string.successfully_deleted)
                        mActionMode?.finish()
                        true
                    }
                    android.R.id.selectAll -> {
                        mAdapter.all(!mAdapter.isCheckedAll())
                        updateResendItemVisible()
                        true
                    }
                    R.id.resend_all -> {
                        val checked = mAdapter.getCheckedItemList()
                        checked.forEach {
                            smsRecordRepository.resetSmsStatus(it)
                            SmsSentStatusReceiver.sendSmsMessage(mContext, it)
                        }
                        mActionMode?.finish()
                        toast(getString(R.string.num_sms_will_resend, checked.size))
                        searchRecords()
                        true
                    }
                    else -> false
                }
            }

            override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
                mode?.menuInflater?.inflate(R.menu.menu_frag_record_action_mode, menu)
                mActionMode = mode
                mResendSelected = menu?.findItem(R.id.resend_all)
                return true
            }

            override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean = false

            override fun onDestroyActionMode(mode: ActionMode?) {
                mAdapter.setItemCheckable(false)
                mActionMode = null
                mResendSelected = null
            }
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        recordDao = SmsDatabaseHelper(mActivity!!)
                .getDao(SmsBean::class.java)

        val view = inflater.inflate(R.layout.fragment_send_record, container, false)
        val recordList = view.findViewById<RecyclerView>(R.id.record_list)
        recordList.layoutManager = LinearLayoutManager(mActivity)

        recordList.adapter = mAdapter
        registerForContextMenu(recordList)

        setHasOptionsMenu(true)
        return view
    }

    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        return when (item?.itemId) {
            R.id.refresh -> {
                searchRecords()
                toast(strId = R.string.refresh_successfully)
                true
            }
            R.id.filter_all,
            R.id.filter_success,
            R.id.filter_failure -> {
                item.isChecked = !item.isChecked
                mFilterId = item.itemId
                searchRecords()
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onContextItemSelected(item: MenuItem?): Boolean {
        return when (item?.itemId) {
            android.R.id.copy -> {
                mLastClick?.let {
                    val data = ClipData.newPlainText("text", "${it.sendTo}\n${it.message}")
                    mClipManager.primaryClip = data
                    toast(strId = R.string.successful_copy)
                }
                true
            }
            R.id.resend -> {
                mLastClick?.let {
                    smsRecordRepository.resetSmsStatus(it)
                    SmsSentStatusReceiver.sendSmsMessage(
                        mContext,
                        it
                    )
                    searchRecords()
                }
                true
            }
            R.id.edit_and_send -> {
                val sms: SmsBean = mLastClick ?: return false
                val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:${sms.sendTo}"))
                intent.putExtra("sms_body", sms.message)
                startActivity(intent)
                true
            }
            R.id.delete -> {
                mLastClick?.let {
                    smsRecordRepository.remove(it)
                    mAdapter.remove(it)
                }
                true
            }
            else -> super.onContextItemSelected(item)
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
        inflater?.inflate(R.menu.menu_frag_sent_record, menu)
        mSearchView = menu?.findItem(R.id.search_record)?.actionView as SearchView?
        mSearchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextChange(p0: String?): Boolean = false
            override fun onQueryTextSubmit(p0: String?): Boolean {
                mSearchKeyword = p0 ?: ""
                searchRecords()
                return true
            }
        })
        mSearchView?.setOnCloseListener {
            mSearchKeyword = ""
            searchRecords()
            false
        }

        menu?.findItem(R.id.filter_all)?.isChecked = true
        mFilterId = R.id.filter_all
        mSearchKeyword = ""
        searchRecords()
    }

    private fun searchRecords() {
        val filter: SmsRecordRepository.Filter = SmsRecordRepository.Filter.valueOf(mFilterId)
        val records = smsRecordRepository.query(filter, mSearchKeyword)

        mAdapter.removeAll()
        mAdapter.addAll(0, records)
    }

    override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
        val inflater = MenuInflater(mContext)
        inflater.inflate(R.menu.menu_record_context, menu)
        if (mLastClick?.isComplete == true && mLastClick?.isSuccess == false) {
            menu?.findItem(R.id.resend)?.isEnabled = true
        }
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        mActivity = activity as BaseActivity
    }

    override fun onDetach() {
        super.onDetach()
        mActivity = null
    }

    override fun onBackPressed(): Boolean {
        return when (mSearchView?.isIconified) {
            false -> {
                mSearchView?.isIconified = true
                true
            }
            else -> false
        }
    }
}